﻿using System;
using System.IO;
using ParserGenerator.CharacterMapping;
using ParserGenerator.GrammarConstruction;
using ParserGenerator.Output;
using ParserGenerator.SyntacticAnalysis;

namespace ParserGenerator.ScannerConstruction
{
    [Serializable]
    public sealed class ScannerAutomaton
    {
        public GrammarDeclaration Grammar { get; internal set; }
        public ScannerAutomatonStartTable Starts { get; internal set; }
        public GrammarTerminalTable Tokens { get; internal set; }
        public LexicalPrecedenceTable LexicalPrecedences { get; internal set; }
        public CharInterval Universal { get; internal set; }
        public CharMap CharMap { get; internal set; }
        public ScannerAutomatonStateTable States { get; private set; }
        public bool UseLiteralFirstResolutions { get; private set; }
        public bool IsEmpty => States.Reductions.Count <= 0;

        internal ScannerAutomaton()
        {
        }

        internal void Build()
        {
            UseLiteralFirstResolutions = Grammar.UseLiteralFirstResolutions;
            States = new ScannerAutomatonStateTable(this);
        }

        public sealed override string ToString()
        {
            using (StringWriter writer = new StringWriter())
            {
                IndentedWriter w = new IndentedWriter(writer);
                ScannerAutomatonTextWriter tw = new ScannerAutomatonTextWriter(w);
                tw.WriteScannerAutomaton(this);
                return writer.ToString().Trim();
            }
        }

        public string ToHtmlString()
        {
            using (StringWriter writer = new StringWriter())
            {
                IndentedWriter w = new IndentedWriter(writer);
                ScannerAutomatonHtmlWriter hw = new ScannerAutomatonHtmlWriter(w);
                hw.WriteScannerAutomaton(this);
                return writer.ToString().Trim();
            }
        }

        public string ToGraphvizString()
        {
            using (StringWriter writer = new StringWriter())
            {
                IndentedWriter w = new IndentedWriter(writer);
                ScannerAutomatonGraphvizWriter gw = new ScannerAutomatonGraphvizWriter(w);
                gw.WriteScannerAutomaton(this);
                return writer.ToString().Trim();
            }
        }
    }
}
